﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using HaloReachApi;
using Service4u2.Common;
using HaloReachApi.Responses;

namespace HaloReachApi.TestConsole
{
    class Program
    {
        private static string apiKey = "[YOURAPIKEY]";

        static void Main(string[] args)
        {
            // Remember to set your Halo API Key in the AppSettings, or modify the code to specify your api key in the service constructors.

            //TestGameMetadataService();

            //TestGameHistoryService();

            //TestGameDetailService();

            GameMetadataExample();

            PlayerDetailsExample();

            var k = Console.ReadKey();
        }
                
        private static void GameMetadataExample()
        {
            // Create the metadata service, passing in our api key.
            // NOTE: Alternatively, the default Constructor will look for a "HaloReachAPIKey" App Setting.
            var metadataService = new GameMetadataService(apiKey);

            bool completed = false;
            metadataService.GotError += (s, e) =>
                {
                    Console.WriteLine("Metadata Service Error: {0}", e.Argument.Message);
                    completed = true;
                };
            metadataService.GotResult += (s, e) =>
                {
                    var response = e.Argument;
                    Console.WriteLine("Metadata Service Response: {0}", response.reason);
                    Console.WriteLine("\tCommendation Count: {0}", response.Data.AllCommendationsById.Count);
                    Console.WriteLine("\tEnemy Count: {0}", response.Data.AllEnemiesById.Count);
                    Console.WriteLine("\tMedal Count: {0}", response.Data.AllMedalsById.Count);
                    Console.WriteLine("\tMaps Count: {0}", response.Data.AllMapsById.Count);
                    Console.WriteLine("\tWeapons Count: {0}", response.Data.AllWeaponsById.Count);

                    completed = true;
                };

            metadataService.GetGameDataAsync();

            // Waiting around for the service to return...
            var start = DateTime.Now;
            while (DateTime.Now.Subtract(start).TotalSeconds < 5)
            {
                if (completed)
                    break;

                Console.WriteLine("Sleeping...");
                Thread.Sleep(1000);
            }

        }

        /// <summary>
        /// An example method for getting a players statistics and details.
        /// </summary>
        private static void PlayerDetailsExample()
        {
            // Using the default constructor will load your API Key from the "HaloReachAPIKey" App Setting.
            var playerDetailsService = new PlayerDetailsService(apiKey);

            bool completed = false;
            playerDetailsService.GotError += (s, e) =>
            {
                Console.WriteLine("Player Details Service Error: {0}", e.Argument.Message);
                completed = true;
            };
            playerDetailsService.GotResult += (s, e) =>
            {
                var response = e.Argument;

                if (response.Player == null)
                {
                    Console.WriteLine("Player not found...");
                    completed = true;
                    return;
                }

                Console.WriteLine("Player Details: {0} ({1})", response.Player.gamertag, response.Player.service_tag);
                
                // Player model image (standard and Hi Res)
                Console.WriteLine("Player Model Url: http://bungie.net" + response.PlayerModelUrl);
                Console.WriteLine("Player Model Url (Hi-Res): http://bungie.net" + response.PlayerModelUrlHiRes);

                // Challenges information
                Console.WriteLine("Daily Challenges Completed: {0}", response.Player.daily_challenges_completed);
                Console.WriteLine("Weekly Challenges Completed: {0}", response.Player.weekly_challenges_completed);

                // Last game type played
                Console.WriteLine("Last Game Type Played: {0}", response.Player.LastGameVariantClassPlayed);

                if (e.Argument.StatisticsByMap != null)
                {
                    foreach (var mapStat in e.Argument.StatisticsByMap)
                    {
                        // Statistics for last played maps.
                        Console.WriteLine("Map Id: {0}", mapStat.MapId);
                        Console.WriteLine("\tTotal Kills: {0}", mapStat.total_kills);
                        Console.WriteLine("\tTotal Deaths: {0}", mapStat.total_deaths);
                        Console.WriteLine("\tTotal Score: {0}", mapStat.total_score);
                        Console.WriteLine("\tTotal Medals: {0}", mapStat.TotalMedals);
                    }
                }

                completed = true;
            };

            // Ask for a gamertag to look up.
            Console.WriteLine("Enter a Gamertag: ");
            var gamerTag = Console.ReadLine();

            // Uncomment this to get details by map, but remember to comment out the NoStats call that is one line below.
            //playerDetailsService.GetPlayerDetailsWithStatsByMapAsync(gamerTag);
            
            playerDetailsService.GetPlayerDetailsNoStatsAsync(gamerTag);

            // Waiting around for the service to return... Takes about 10 seconds for player details calls
            var start = DateTime.Now;
            while (DateTime.Now.Subtract(start).TotalSeconds < 20)
            {
                if (completed)
                    break;

                Console.WriteLine("Sleeping...");
                Thread.Sleep(1000);
            }
        }

        private static void TestGameDetailService()
        {
            TestServiceCommon<GameDetailsService, GameDetailsResponse>(new GameDetailsService(),
                serv =>
                {
                    Console.Write("GameId: ");
                    var gameId = Console.ReadLine();
                    serv.GetGameDetailsAsync(gameId);
                },
                (s, e) =>
                {
                    Console.WriteLine("Game Time: {0}", e.Argument.GameDetails.GameTimestamp);
                    Console.WriteLine("Players: ");
                    foreach (var pl in e.Argument.GameDetails.Players)
                    {
                        Console.WriteLine(pl.PlayerDetail == null ? "[null]" : pl.PlayerDetail.gamertag);
                    }
                });
        }

        private static void TestGameMetadataService()
        {
            TestServiceCommon<GameMetadataService, GameMetadataResponse>(new GameMetadataService(),
                serv => serv.GetGameDataAsync(),
                (s, e) => Console.WriteLine("Metadata Service Response: {0}, {1}", e.Argument.status, e.Argument.Data.AllCommendationsById.Count));            
            
        }

        private static void TestGameHistoryService()
        {
            TestServiceCommon<GameHistoryService, GameHistoryResponse>(new GameHistoryService(),
                serv =>
                {
                    Console.Write("Gametag for history: ");
                    var gamer = Console.ReadLine();
                    serv.GetGameHistoryAsync(gamer);
                },
                (s, e) =>
                {
                    foreach (var gm in e.Argument.RecentGames)
                    {
                        Console.WriteLine(String.Format("Game Id: {3}\r\n\tScore: {0}\r\n\tKills: {1}\r\n\tRating: {2}", gm.RequestedPlayerScore, gm.RequestedPlayerKills, gm.RequestedPlayerRating, gm.GameId));
                    }
                });
        }

        private static void TestServiceCommon<TService, TResponse>(TService service, Action<TService> startAction, Action<object, EventArgs<TResponse>> resultAction)
            where TResponse : new()
            where TService : BaseReachApiJsonService<TResponse>
        {
            var serv = service;
            bool completed = false;

            serv.GotError += (s, e) =>
                {
                    Console.WriteLine("Metadata Service Error: {0}", e.Argument.Message);
                    completed = true;
                };
            serv.GotResult += (s, e) =>
                {
                    resultAction(s, e);
                    completed = true;
                };

            startAction(serv);

            var start = DateTime.Now;
            while (DateTime.Now.Subtract(start).TotalSeconds < 5)
            {
                if (completed)
                    break;

                Console.WriteLine("Sleeping...");
                Thread.Sleep(1000);
            }
        }
    }
}
